home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Graphics / sKulpt / skulpt-src / win-src / Objects-Base.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-27  |  34.6 KB  |  1,232 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16.  
  17. // Includes utilitaires D3D
  18. #include "d3dmath.h"
  19. #include "d3dutil.h"
  20. #include "D3DEnum.h"
  21.  
  22. #include <d3dx.h>
  23.  
  24. // Ids Resources
  25. #include "resource.h"
  26.  
  27. // Constantes
  28. #include "const.h"
  29.  
  30. // Types
  31. #include "types.h"
  32.  
  33. // Variables globales projet
  34. #include "vars.h"
  35.  
  36. // Prototypes fonctions autres modules
  37. #include "proto.h"
  38.  
  39. // Macros
  40. #include "macros.h"
  41.  
  42. //************************************* C O M M U N S ***********************
  43. void vDeleteObjects(void)
  44. {
  45.     // RAZ points
  46.     for (int iVert = 0 ; iVert < XDC_NUMPT ; iVert++)
  47.     {
  48.         Vertices[iVert].bEnabled = FALSE;
  49.         Vertices[iVert].bHidden = FALSE;
  50.         Vertices[iVert].bSelected = FALSE;
  51.         Vertices[iVert].bSmooth = FALSE;
  52.         Vertices[iVert].iDepend = 0;
  53.     }
  54.     iVertFirstAvailable = 0;
  55.     iVertLastUsed = -1;
  56.  
  57.     // RAZ arêtes
  58.     for (int iEdge = 0 ; iEdge < XDC_NUMEDGE ; iEdge++)
  59.     {
  60.         Edges[iEdge].bEnabled = FALSE;
  61.         Edges[iEdge].bHidden = FALSE;
  62.     }
  63.     iEdgeFirstAvailable = 0;
  64.     iEdgeLastUsed = -1;
  65.  
  66.     // RAZ lampes
  67.     for (int iLamp = 0 ; iLamp < XDC_NUMLAMP ; iLamp++)
  68.         if (Lampes[iLamp].bEnabled) bDeleteLamp(iLamp);
  69.  
  70.     iLampFirstAvailable = 0;
  71.     iLampLastUsed = -1;
  72.  
  73.     // RAZ facettes
  74.     for (int iTriangle = 0 ; iTriangle < XDC_NUMTRI ; iTriangle++)
  75.     {
  76.         Triangles[iTriangle].bEnabled = FALSE;
  77.         Triangles[iTriangle].bHidden = FALSE;
  78.     }
  79.     iTriaFirstAvailable = 0;
  80.     iTriaLastUsed = -1;
  81.  
  82.     // RAZ matériaux
  83.     for (int iMtrl = 0 ; iMtrl < XDC_NUMMTRL ; iMtrl++)
  84.         Materials[iMtrl].bEnabled = FALSE;
  85.     iMtrlFirstAvailable = 0;
  86.     iMtrlLastUsed = -1;
  87.  
  88. #ifndef _AMIGA_
  89.     // RAZ Objets D3D
  90.     vDeleteD3DObjects();
  91. #endif
  92. }
  93.  
  94. //************************************** M A T E R I A L S *************************
  95. BOOL bSameMaterial(D3DMATERIAL7 *hMtrl1, D3DMATERIAL7 *hMtrl2)
  96. {
  97.     double fDist =
  98.                     fabs(hMtrl2 -> ambient.a - hMtrl1 -> ambient.a) +
  99.                     fabs(hMtrl2 -> ambient.r - hMtrl1 -> ambient.r) +
  100.                     fabs(hMtrl2 -> ambient.g - hMtrl1 -> ambient.g) +
  101.                     fabs(hMtrl2 -> ambient.b - hMtrl1 -> ambient.b) +
  102.  
  103.                     fabs(hMtrl2 -> diffuse.a - hMtrl1 -> diffuse.a) +
  104.                     fabs(hMtrl2 -> diffuse.r - hMtrl1 -> diffuse.r) +
  105.                     fabs(hMtrl2 -> diffuse.g - hMtrl1 -> diffuse.g) +
  106.                     fabs(hMtrl2 -> diffuse.b - hMtrl1 -> diffuse.b) +
  107.  
  108.                     fabs(hMtrl2 -> specular.a - hMtrl1 -> specular.a) +
  109.                     fabs(hMtrl2 -> specular.r - hMtrl1 -> specular.r) +
  110.                     fabs(hMtrl2 -> specular.g - hMtrl1 -> specular.g) +
  111.                     fabs(hMtrl2 -> specular.b - hMtrl1 -> specular.b) +
  112.                     fabs(hMtrl2 -> power - hMtrl1 -> power);
  113.  
  114.     return (fDist < 0.1);
  115. }
  116.  
  117. int iFindMaterial(D3DMATERIAL7 *hMtrl, int iPrevious)
  118. {
  119.     int iCnt;
  120.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  121.     
  122.     // Rechercher le matériau
  123.     for (iCnt = max(iPrevious + 1, 0) ;
  124.             (iCnt <= iMtrlLastUsed)
  125.          && (!(   (Materials[iCnt].bEnabled == TRUE)
  126.                && (!bSameMaterial(hMtrl, &(Materials[iCnt].mtrl)))
  127.               ))
  128.          ;
  129.          iCnt++) ;
  130.  
  131.     // Si matériau trouvé alors renvoyer son indice
  132.     if (iCnt <= iMtrlLastUsed)
  133.         return(iCnt);
  134.  
  135.     // Sinon renvoyer -1
  136.     return -1;
  137. }
  138.  
  139. int iMakeMaterial(D3DMATERIAL7 *hMtrl, char *sName, BOOL bSame)
  140. {
  141.     int iCnt;
  142.     
  143.     // Rechercher le premier index libre
  144.     for (iCnt = bSame ? 0 : iMtrlFirstAvailable ;
  145.             (iCnt <= iMtrlLastUsed)
  146.          && (   ((!bSame) && (Materials[iCnt].bEnabled == TRUE))
  147.              || ((bSame) && (!(       (Materials[iCnt].bEnabled == TRUE) 
  148.                                 && (bSameMaterial(hMtrl, &(Materials[iCnt].mtrl)))
  149.                 )            ) )
  150.             ) ;
  151.          iCnt++) ;
  152.  
  153.     // Si limite tableau atteinte alors renvoyer erreur
  154.     if (iCnt >= XDC_NUMMTRL)
  155.     {
  156.         vTrace("*** E0016 : Plus de slots matériaux libres");
  157.         return -1;
  158.     }
  159.  
  160.     // Si matériau trouvé dans tableau alors le renvoyer
  161.     if (bSame)
  162.     {
  163.         if ((iCnt < XDC_NUMMTRL) && (Materials[iCnt].bEnabled == TRUE) 
  164.                                  && (bSameMaterial(hMtrl, &(Materials[iCnt].mtrl))))
  165.             return(iCnt);
  166.         else
  167.             return(iMakeMaterial(hMtrl, sName, XDC_FORCENEW));
  168.     }
  169.  
  170.     // Créer un nouveau point
  171.     Materials[iCnt].mtrl = *hMtrl;
  172.     strcpy(Materials[iCnt].sName, sName);
  173.     Materials[iCnt].bEnabled  =TRUE;
  174.  
  175.     while (Materials[iMtrlFirstAvailable].bEnabled == TRUE) iMtrlFirstAvailable++;
  176.     if (iMtrlLastUsed < iCnt) iMtrlLastUsed = iCnt;
  177.  
  178.     return iCnt;
  179. }
  180.  
  181.  
  182. BOOL bDeleteMaterial(int iMtrl)
  183. {
  184.     // Si le material n'est pas enabled alors ne rien faire
  185.     if (Materials[iMtrl].bEnabled == FALSE) return FALSE;
  186.  
  187.     // Disabler le point
  188.     Materials[iMtrl].bEnabled = FALSE;
  189.     
  190.     // Mettre à jour les indices globaux du tableau des vertices
  191.     if (iMtrl == iMtrlLastUsed) while ((iMtrlLastUsed > -1) && (!Materials[--iMtrlLastUsed].bEnabled)) ;
  192.     if (iMtrl < iMtrlFirstAvailable) iMtrlFirstAvailable = iMtrl;
  193.  
  194.     return TRUE;
  195. }
  196.  
  197. //************************************** V E R T E X *************************
  198. int iFindVertex(D3DVECTOR p, int iPrevious)
  199. {
  200.     int iCnt;
  201.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  202.     
  203.     // Rechercher le point
  204.     for (iCnt = max(iPrevious + 1, 0) ;
  205.             (iCnt <= iVertLastUsed)
  206.          && (!(   (Vertices[iCnt].bEnabled == TRUE)
  207.                && (Vertices[iCnt].bHidden == FALSE)
  208.                && (fabs(Vertices[iCnt].vPoint.x - p.x) < fTolerance)
  209.                && (fabs(Vertices[iCnt].vPoint.y - p.y) < fTolerance)
  210.                && (fabs(Vertices[iCnt].vPoint.z - p.z) < fTolerance)
  211.               ))
  212.          ;
  213.          iCnt++) ;
  214.  
  215.     // Si point trouvé alors renvoyer son indice
  216.     if (iCnt <= iVertLastUsed)
  217.         return(iCnt);
  218.  
  219.     // Sinon renvoyer -1
  220.     return -1;
  221. }
  222.  
  223. int iMakeVertex(D3DVECTOR p, BOOL bSame)
  224. {
  225.     int iCnt;
  226.     
  227.     // Rechercher le premier index libre
  228.     for (iCnt = bSame ? 0 : iVertFirstAvailable ;
  229.             (iCnt <= iVertLastUsed)
  230.          && (   ((!bSame) && (Vertices[iCnt].bEnabled == TRUE))
  231.              || ((bSame) && (!((Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))))
  232.             ) ;
  233.          iCnt++) ;
  234.  
  235.     // Si limite tableau atteinte alors renvoyer erreur
  236.     if (iCnt >= XDC_NUMPT)
  237.     {
  238.         vTrace("*** E0016 : Plus de slots vertex libres");
  239.         return -1;
  240.     }
  241.  
  242.     // Si point trouvé dans tableau alors le renvoyer
  243.     if (bSame)
  244.     {
  245.         if ((iCnt < XDC_NUMPT) && (Vertices[iCnt].bEnabled == TRUE) && (Vertices[iCnt].bHidden == FALSE) && (Magnitude(Vertices[iCnt].vPoint - p) < 10.f * g_EPSILON))
  246.             return(iCnt);
  247.         else
  248.             return(iMakeVertex(p, XDC_FORCENEW));
  249.     }
  250.  
  251.     // Créer un nouveau point
  252.     Vertices[iCnt].vPoint = p;
  253.     Vertices[iCnt].bSelected = FALSE;
  254.     Vertices[iCnt].bHidden = FALSE;
  255.     Vertices[iCnt].bEnabled  =TRUE;
  256.  
  257.     while (Vertices[iVertFirstAvailable].bEnabled == TRUE) iVertFirstAvailable++;
  258.     if (iVertLastUsed < iCnt) iVertLastUsed = iCnt;
  259.  
  260.     return iCnt;
  261. }
  262.  
  263. BOOL bVertInEdge(int iVert, int iEdge)
  264. {
  265.     if (    (Edges[iEdge].iSommets[0] == iVert)
  266.          || (Edges[iEdge].iSommets[1] == iVert)
  267.        )
  268.         return TRUE;
  269.     else
  270.         return FALSE;
  271. }
  272.  
  273. BOOL bVertInTriangle(int iVert, int iTriangle)
  274. {
  275.     if (    (Triangles[iTriangle].iSommets[0] == iVert)
  276.          || (Triangles[iTriangle].iSommets[1] == iVert)
  277.          || (Triangles[iTriangle].iSommets[2] == iVert)
  278.        )
  279.         return TRUE;
  280.     else
  281.         return FALSE;
  282. }
  283.  
  284. int iEdgesPerVert(int iVert)
  285. {
  286.     int iCnt, jCnt = 0;
  287.  
  288.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  289.         if (bVertInEdge(iVert, iCnt))
  290.             jCnt++;
  291.  
  292.     return jCnt;
  293. }
  294.  
  295. int iTrianglesPerVert(int iVert)
  296. {
  297.     int iCnt, jCnt = 0;
  298.  
  299.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  300.         if (bVertInTriangle(iVert, iCnt))
  301.             jCnt++;
  302.  
  303.     return jCnt;
  304. }
  305.  
  306. BOOL bDeleteVertex(int iVert)
  307. {
  308.     int iCnt;
  309.  
  310.     // Si le point n'est pas enabled alors ne rien faire
  311.     if (Vertices[iVert].bEnabled == FALSE) return FALSE;
  312.  
  313.     // Disabler le point
  314.     Vertices[iVert].bEnabled = FALSE;
  315.     
  316.     // Mettre à jour les indices globaux du tableau des vertices
  317.     if (iVert == iVertLastUsed) while ((iVertLastUsed > -1) && (!Vertices[--iVertLastUsed].bEnabled)) ;
  318.     if (iVert < iVertFirstAvailable) iVertFirstAvailable = iVert;
  319.  
  320.     // Supprimer toutes les arêtes desquelles le sommet supprimé est une extrêmité
  321.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  322.         if (bVertInEdge(iVert, iCnt))
  323.             bDeleteEdge(iCnt);
  324.  
  325.     // Pour tout triangle duquel le sommet supprimé est un sommet, transformer le triangle en une arête entre les 2 sommets restants
  326.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  327.         if (bVertInTriangle(iVert, iCnt))
  328.         {
  329.             /*
  330.             if (Triangles[iCnt].iSommets[0] == iVert) iMakeEdge(Triangles[iCnt].iSommets[1], Triangles[iCnt].iSommets[2]);
  331.             if (Triangles[iCnt].iSommets[1] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[2]);
  332.             if (Triangles[iCnt].iSommets[2] == iVert) iMakeEdge(Triangles[iCnt].iSommets[0], Triangles[iCnt].iSommets[1]);
  333.             */
  334.             bDeleteTriangle(iCnt);
  335.         }
  336.  
  337.     return TRUE;
  338. }
  339.  
  340. #ifndef _AMIGA_
  341. BOOL bSmoothNorm(int iVertex)
  342. {
  343.     if (Vertices[iVertex].bEnabled == FALSE) return FALSE;
  344.     if (Vertices[iVertex].bSmooth == FALSE) return FALSE;
  345.     if (Vertices[iVertex].iDepend == 0) return FALSE;
  346.  
  347.     D3DVECTOR vn = D3DVECTOR(0.f, 0.f, 0.f);
  348.  
  349.     for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  350.     {
  351.         if (Triangles[iTriangle].bEnabled == FALSE) continue;
  352.         if (!bVertInTriangle(iVertex, iTriangle)) continue;
  353.  
  354.         D3DVECTOR vc;
  355. /*
  356.         short iS0 = Triangles [iTriangle].iSommets[0],
  357.               iS1 = Triangles [iTriangle].iSommets[1],
  358.               iS2 = Triangles [iTriangle].iSommets[2];
  359.  
  360.         D3DVECTOR
  361.                 v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  362.                 v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  363.                 v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  364.                 vn0, vn1, vn2;
  365.  
  366.         vn0 = Normalize(CrossProduct(v01, v02));
  367.         vn1 = Normalize(CrossProduct(v01, v12));
  368.         vn2 = Normalize(CrossProduct(v02, v12));
  369.  
  370. */
  371.         for (int iCnt = 0 ; iCnt < 3 ; iCnt++)
  372.             if (iVertex == Triangles [iTriangle].iSommets[iCnt])
  373.                 vc = D3DVECTOR(
  374.                     Triangles [iTriangle].pSommets[iCnt].nx,
  375.                     Triangles [iTriangle].pSommets[iCnt].ny,
  376.                     Triangles [iTriangle].pSommets[iCnt].nz);
  377.  
  378. /*
  379.         if (iVertex == iS0) vc = vn0;
  380.         if (iVertex == iS1) vc = vn1;
  381.         if (iVertex == iS2) vc = vn2;
  382.  
  383.         float fdp = DotProduct(vn, vc);
  384.  
  385.         if (fdp >= 0)
  386. */
  387.             vn += vc;
  388. /*
  389.         else
  390.             vn -= vc;
  391. */
  392.     }
  393.  
  394.     Vertices[iVertex].vNormal = Normalize(vn);
  395.  
  396.     return TRUE;
  397. }
  398. #endif
  399.  
  400. BOOL bIsVertexSelected(int iVertex)
  401. {
  402.     return
  403.         Vertices[iVertex].bEnabled && Vertices[iVertex].bSelected;
  404. }
  405.  
  406. //************************************** L A M P E S *************************
  407. int iFindLamp(D3DVECTOR p, int iPrevious)
  408. {
  409.     int iCnt;
  410.     float fTolerance = (float) fabs(fXmax - fXmin) / XDC_ZONE;
  411.     
  412.     // Rechercher la lampe
  413.     for (iCnt = max(iPrevious + 1, 0) ;
  414.             (iCnt <= iLampLastUsed)
  415.          && (!(   (Lampes[iCnt].bEnabled == TRUE)
  416.                && (fabs(Lampes[iCnt].lLamp.dvPosition.x - p.x) < fTolerance)
  417.                && (fabs(Lampes[iCnt].lLamp.dvPosition.y - p.y) < fTolerance)
  418.                && (fabs(Lampes[iCnt].lLamp.dvPosition.z - p.z) < fTolerance)
  419.               ))
  420.          ;
  421.          iCnt++) ;
  422.  
  423.     // Si point trouvé alors renvoyer son indice
  424.     if (iCnt <= iLampLastUsed)
  425.         return(iCnt);
  426.  
  427.     // Sinon renvoyer -1
  428.     return -1;
  429. }
  430.  
  431. int iMakeLamp(
  432.     D3DLIGHTTYPE    dltType,            /* Type of light source */
  433.     D3DCOLORVALUE   dcvDiffuse,         /* Diffuse color of light */
  434.     D3DCOLORVALUE   dcvSpecular,        /* Specular color of light */
  435.     D3DCOLORVALUE   dcvAmbient,         /* Ambient color of light */
  436.     D3DVECTOR       dvPosition,         /* Position in world space */
  437.     D3DVECTOR       dvDirection,        /* Direction in world space */
  438.     D3DVALUE        dvRange,            /* Cutoff range */
  439.     D3DVALUE        dvFalloff,          /* Falloff */
  440.     D3DVALUE        dvAttenuation0,     /* Constant attenuation */
  441.     D3DVALUE        dvAttenuation1,     /* Linear attenuation */
  442.     D3DVALUE        dvAttenuation2,     /* Quadratic attenuation */
  443.     D3DVALUE        dvTheta,            /* Inner angle of spotlight cone */
  444.     D3DVALUE        dvPhi               /* Outer angle of spotlight cone */
  445. )
  446. {
  447.     int iCnt;
  448.     
  449.     // Rechercher le premier index libre
  450.     for (iCnt = iLampFirstAvailable ;
  451.             (iCnt <= iLampLastUsed)
  452.          && (Lampes[iCnt].bEnabled == TRUE) ;
  453.          iCnt++) ;
  454.  
  455.     // Si limite tableau atteinte alors renvoyer erreur
  456.     if (iCnt >= XDC_NUMLAMP)
  457.     {
  458.         vTrace("*** E0017 : Plus de slots vertex libres");
  459.         return -1;
  460.     }
  461.  
  462.     // Créer une nouvelle lampe
  463.     ZeroMemory(&Lampes[iCnt].lLamp, sizeof(D3DLIGHT7));
  464.     Lampes[iCnt].bEnabled = TRUE;
  465.     Lampes[iCnt].bSelected = FALSE;
  466.     Lampes[iCnt].bLit = TRUE;
  467.     Lampes[iCnt].lLamp.dltType = dltType; // D3DLIGHT_POINT ou D3DLIGHT_DIRECTIONAL ou D3DLIGHT_SPOT
  468.     Lampes[iCnt].lLamp.dcvDiffuse = dcvDiffuse;
  469.     Lampes[iCnt].lLamp.dcvSpecular = dcvSpecular;
  470.     Lampes[iCnt].lLamp.dcvAmbient = dcvAmbient;
  471.     Lampes[iCnt].lLamp.dvPosition = dvPosition;
  472.     Lampes[iCnt].lLamp.dvDirection = dvDirection;
  473.     Lampes[iCnt].lLamp.dvRange = dvRange;
  474.     Lampes[iCnt].lLamp.dvFalloff = dvFalloff;
  475.     Lampes[iCnt].lLamp.dvAttenuation0 = dvAttenuation0; 
  476.     Lampes[iCnt].lLamp.dvAttenuation1 = dvAttenuation1; 
  477.     Lampes[iCnt].lLamp.dvAttenuation2 = dvAttenuation2; 
  478.     Lampes[iCnt].lLamp.dvTheta = dvTheta; 
  479.     Lampes[iCnt].lLamp.dvPhi = dvPhi; 
  480.  
  481. #ifndef NO3D
  482.     lpd3dDevice->SetLight(iCnt, &Lampes[iCnt].lLamp);
  483.     lpd3dDevice->LightEnable(iCnt, Lampes[iCnt].bLit);
  484. #endif
  485.  
  486.     while (Lampes[iLampFirstAvailable].bEnabled == TRUE) iLampFirstAvailable++;
  487.     if (iLampLastUsed < iCnt) iLampLastUsed = iCnt;
  488.  
  489.     return iCnt;
  490. }
  491.  
  492. BOOL bUpdateLamp(int iLamp)
  493. {
  494.     // Si la lampe n'est pas enabled alors ne rien faire
  495.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  496.  
  497. #ifndef NO3D
  498.     lpd3dDevice->SetLight(iLamp, &Lampes[iLamp].lLamp);
  499.     lpd3dDevice->LightEnable(iLamp, Lampes[iLamp].bLit);
  500. #endif
  501.  
  502.     return TRUE;
  503. }
  504.  
  505. BOOL bDeleteLamp(int iLamp)
  506. {
  507.     // Si la lampe n'est pas enabled alors ne rien faire
  508.     if (Lampes[iLamp].bEnabled == FALSE) return FALSE;
  509.  
  510.     // Disabler la lampe
  511. #ifndef NO3D
  512.     lpd3dDevice->LightEnable(iLamp, FALSE);
  513. #endif
  514.     Lampes[iLamp].bEnabled = FALSE;
  515.     Lampes[iLamp].bLit = FALSE;
  516.     
  517.     // Mettre à jour les indices globaux du tableau des lampes
  518.     if (iLamp == iLampLastUsed) while ((iLampLastUsed > -1) && (!Lampes[--iLampLastUsed].bEnabled)) ;
  519.     if (iLamp < iLampFirstAvailable) iLampFirstAvailable = iLamp;
  520.  
  521.     return TRUE;
  522. }
  523.  
  524. //************************************** E D G E S ***************************
  525. int iFindEdge(int i1, int i2)
  526. {
  527.     int iCnt;
  528.  
  529.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  530.         if (    ((Edges[iCnt].iSommets[0] == i1) || (Edges[iCnt].iSommets[1] == i1))
  531.              && ((Edges[iCnt].iSommets[0] == i2) || (Edges[iCnt].iSommets[1] == i2))
  532.            )
  533.            return iCnt;
  534.  
  535.     return -1;
  536. }
  537.  
  538. int iMakeEdge(int i1, int i2)
  539. {
  540.     int iCnt;
  541.  
  542.     // Rechercher un slot d'arête libre
  543.     for (iCnt = iEdgeFirstAvailable ; (iCnt <= iEdgeLastUsed) && (Edges [iCnt].bEnabled == TRUE) ; iCnt++);
  544.  
  545.     // Si pas trouvé alors fail
  546.     if (iCnt >= XDC_NUMEDGE)
  547.     {
  548.         vTrace("*** E0018 : Plus de slots arêtes libres");
  549.         return -1;
  550.     }
  551.  
  552.     // Créer l'arête
  553.     Edges [iCnt].iSommets[0] = i1;
  554.     Edges [iCnt].iSommets[1] = i2;
  555.  
  556.     Edges[iCnt].bEnabled = TRUE;
  557.     Edges[iCnt].bHidden = FALSE;
  558.  
  559.     while (Edges[iEdgeFirstAvailable].bEnabled == TRUE) iEdgeFirstAvailable++;
  560.     if (iEdgeLastUsed < iCnt) iEdgeLastUsed = iCnt;
  561.     
  562.     return iCnt;
  563. }
  564.  
  565. BOOL bDeleteEdge(int iEdge)
  566. {
  567.     // Si l'arête n'est pas enabled alors ne rien faire
  568.     if (Edges[iEdge].bEnabled == FALSE) return FALSE;
  569.  
  570.     // Disabler l'arête
  571.     Edges[iEdge].bEnabled = FALSE;
  572.     
  573.     // Mettre à jour les indices globaux du tableau des arêtes
  574.     if (iEdge == iEdgeLastUsed) while ((iEdgeLastUsed > -1) && !(Edges[--iEdgeLastUsed].bEnabled)) ;
  575.     if (iEdge < iEdgeFirstAvailable) iEdgeFirstAvailable = iEdge;
  576.  
  577.     return TRUE;
  578. }
  579.  
  580. BOOL    bIsEdgeSelected(int iEdge)
  581. {
  582.     return
  583.         Edges[iEdge].bEnabled &&
  584.         bIsVertexSelected(Edges[iEdge].iSommets[0]) &&
  585.         bIsVertexSelected(Edges[iEdge].iSommets[1]);
  586. }
  587.  
  588. BOOL    bIsEdgePartiallySelected(int iEdge)
  589. {
  590.     return 
  591.         Edges[iEdge].bEnabled &&
  592.         (bIsVertexSelected(Edges[iEdge].iSommets[0]) ||
  593.          bIsVertexSelected(Edges[iEdge].iSommets[1]));
  594. }
  595.  
  596. //************************************** T R I A N G L E S *******************
  597. int iFindTriangle(int i1, int i2, int i3)
  598. {
  599.     int iCnt;
  600.  
  601.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  602.         if (    ((Triangles[iCnt].iSommets[0] == i1) || (Triangles[iCnt].iSommets[1] == i1) || (Triangles[iCnt].iSommets[2] == i1))
  603.              && ((Triangles[iCnt].iSommets[0] == i2) || (Triangles[iCnt].iSommets[1] == i2) || (Triangles[iCnt].iSommets[2] == i2))
  604.              && ((Triangles[iCnt].iSommets[0] == i3) || (Triangles[iCnt].iSommets[1] == i3) || (Triangles[iCnt].iSommets[2] == i3))
  605.            )
  606.            return iCnt;
  607.  
  608.     return -1;
  609. }
  610.  
  611. int iMakeTriangle(int i1, int i2, int i3, unsigned char bRouge, unsigned char bVert, unsigned char bBleu)
  612. {
  613.     int iCnt;
  614.  
  615.     // Rechercher un slot de triangle libre
  616.     for (iCnt = iTriaFirstAvailable ; (iCnt <= iTriaLastUsed) && (Triangles [iCnt].bEnabled == TRUE) ; iCnt++);
  617.  
  618.     // Si pas trouvé alors fail
  619.     if (iCnt >= XDC_NUMTRI)
  620.     {
  621.         vTrace("*** E0019 : Plus de slots triangles libres");
  622.         return -1;
  623.     }
  624.  
  625.     // Créer le triangle
  626.     Triangles [iCnt].iSommets[0] = i1;
  627.     Triangles [iCnt].iSommets[1] = i2;
  628.     Triangles [iCnt].iSommets[2] = i3;
  629.  
  630.     // Incrémenter le compteur de triangles des sommets
  631.     Vertices[Triangles [iCnt].iSommets[0]].iDepend++;
  632.     Vertices[Triangles [iCnt].iSommets[1]].iDepend++;
  633.     Vertices[Triangles [iCnt].iSommets[2]].iDepend++;
  634.  
  635.     // Affecter couleur et aspect
  636.     D3DMATERIAL7 Mtrl, *pMtrl = &Mtrl; // = &Triangles[iCnt].mtrl;
  637.     ZeroMemory(pMtrl, sizeof(D3DMATERIAL7));
  638.     pMtrl -> ambient.a = 0.5f;
  639.     pMtrl -> ambient.r = (float) bRouge / 256.f / 6.f;
  640.     pMtrl -> ambient.g = (float) bVert / 256.f / 6.f;
  641.     pMtrl -> ambient.b = (float) bBleu / 256.f / 6.f;
  642.  
  643.     pMtrl -> diffuse.a = 0.5f;
  644.     pMtrl -> diffuse.r = (float) bRouge / 256.f;
  645.     pMtrl -> diffuse.g = (float) bVert / 256.f;
  646.     pMtrl -> diffuse.b = (float) bBleu / 256.f;
  647.  
  648.     pMtrl -> specular.a = 0.5f;
  649.     pMtrl -> specular.r = 1.f;
  650.     pMtrl -> specular.g = 1.f;
  651.     pMtrl -> specular.b = 1.f;
  652.     pMtrl -> power = 1.f;
  653.  
  654.     Triangles[iCnt].iMtrl = iMakeMaterial(pMtrl, "", XDC_ALLOWSAME);
  655.     Triangles[iCnt].bEnabled = TRUE;
  656.     Triangles[iCnt].bHidden = FALSE;
  657.  
  658. #ifndef _AMIGA_
  659.     // Mettre à jour les coordonnées du triangle D3D correspondant
  660.     bUpdateD3DTri(iCnt);
  661. #endif
  662.  
  663.     while (Triangles[iTriaFirstAvailable].bEnabled == TRUE) iTriaFirstAvailable++;
  664.     if (iTriaLastUsed < iCnt) iTriaLastUsed = iCnt;
  665.     
  666.     return iCnt;
  667. }
  668.  
  669. BOOL bDeleteTriangle(int iTriangle)
  670. {
  671.     // Si le triangle n'est pas enabled alors ne rien faire
  672.     if (Triangles[iTriangle].bEnabled == FALSE) return FALSE;
  673.  
  674.     // Disabler le triangle
  675.     Triangles[iTriangle].bEnabled = FALSE;
  676.     
  677.     // Mettre à jour les indices globaux du tableau des triangles
  678.     if (iTriangle == iTriaLastUsed) while ((iTriaLastUsed > -1) && (!Triangles[--iTriaLastUsed].bEnabled)) ;
  679.     if (iTriangle < iTriaFirstAvailable) iTriaFirstAvailable = iTriangle;
  680.  
  681.     // Décrémenter le compteur de triangles des sommets
  682.     Vertices[Triangles [iTriangle].iSommets[0]].iDepend--;
  683.     Vertices[Triangles [iTriangle].iSommets[1]].iDepend--;
  684.     Vertices[Triangles [iTriangle].iSommets[2]].iDepend--;
  685.  
  686.     return TRUE;
  687. }
  688.  
  689. #ifndef _AMIGA_
  690. BOOL bUpdateD3DTri(int iCnt)
  691. {
  692.     if (Triangles[iCnt].bEnabled == FALSE) return FALSE;
  693.     
  694.     short iS0 = Triangles [iCnt].iSommets[0],
  695.           iS1 = Triangles [iCnt].iSommets[1],
  696.           iS2 = Triangles [iCnt].iSommets[2];
  697.  
  698.     D3DVECTOR
  699.             v01 = Vertices[iS1].vPoint - Vertices[iS0].vPoint,
  700.             v02 = Vertices[iS2].vPoint - Vertices[iS0].vPoint,
  701.             v12 = Vertices[iS2].vPoint - Vertices[iS1].vPoint,
  702.             vn0, vn1, vn2,
  703.             v1, v2, vp2, v3, v4;
  704.     
  705.     D3DMATRIX p;
  706.  
  707.     // Calculer la normale au point 0 : v3
  708.     v1 = Normalize(v01);
  709.     v2 = Normalize(v02);
  710.     v3 = Normalize(CrossProduct(v01, v02));
  711.     
  712.     // On fait un repère orthonormal avec v3 et v1 (qui sont orthonormés) et leur produit vectoriel
  713.     vp2 = Normalize(CrossProduct(v3, v1));
  714.  
  715.     // On fait la matrice de changement de repère 
  716.     D3DUtil_SetIdentityMatrix(p);
  717.     p._11 = v1.x;
  718.     p._21 = v1.y;
  719.     p._31 = v1.z;
  720.     p._12 = vp2.x;
  721.     p._22 = vp2.y;
  722.     p._32 = vp2.z;
  723.     p._13 = v3.x;
  724.     p._23 = v3.y;
  725.     p._33 = v3.z;
  726.  
  727.     // on calcule l'image de z dans le nouveau repère : v4
  728.     D3DMath_VectorMatrixMultiply(v4, D3DVECTOR(0.f, 0.f, 1.f), p);
  729.  
  730.     // On vérifie que v4 est dans le même sens que z, ce qui nous dit si le triangle est CW ou CCW
  731.     float fSign = DotProduct(D3DVECTOR(0.f, 0.f, 1.f), v4);
  732.  
  733.     // On calcule les vecteurs normaux
  734.     if (Vertices[iS0].bSmooth) { bSmoothNorm(iS0); vn0 = Vertices[iS0].vNormal; }
  735.     else vn0 = Normalize(CrossProduct(v01, v02));
  736.  
  737.     if (Vertices[iS1].bSmooth) { bSmoothNorm(iS1); vn1 = Vertices[iS1].vNormal; }
  738.     else vn1 = Normalize(CrossProduct(v01, v12));
  739.  
  740.     if (Vertices[iS2].bSmooth) { bSmoothNorm(iS2); vn2 = Vertices[iS2].vNormal; }
  741.     else vn2 = Normalize(CrossProduct(v02, v12));
  742.  
  743.     // Créer les 2 triangles D3D (CW, CCW) en ordonnant les sommets pour avoir les CCW en 1er
  744.     if (fSign >= 0)
  745.     {
  746.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  747.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  748.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  749.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  750.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  751.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  752.     }
  753.     else
  754.     {
  755.         Triangles [iCnt].pSommets[0] = D3DVERTEX(Vertices[iS0].vPoint, -vn0, 0, 0);
  756.         Triangles [iCnt].pSommets[1] = D3DVERTEX(Vertices[iS2].vPoint, -vn2, 0, 0);
  757.         Triangles [iCnt].pSommets[2] = D3DVERTEX(Vertices[iS1].vPoint, -vn1, 0, 0);
  758.         Triangles [iCnt].pSommets[3] = D3DVERTEX(Vertices[iS0].vPoint, vn0, 0, 0);
  759.         Triangles [iCnt].pSommets[4] = D3DVERTEX(Vertices[iS1].vPoint, vn1, 0, 0);
  760.         Triangles [iCnt].pSommets[5] = D3DVERTEX(Vertices[iS2].vPoint, vn2, 0, 0);
  761.     }
  762.  
  763.     return TRUE;
  764. }
  765. #endif
  766.  
  767. BOOL bSubdivideTriangle(int iTriangle)
  768. {
  769.     int iNewV[3], iNewT[4];
  770.     
  771.     if (Triangles[iTriangle].bEnabled == FALSE) return(FALSE);
  772.  
  773.     unsigned char uR = (unsigned char) (Materials[Triangles[iTriangle].iMtrl].mtrl.diffuse.r * 255.f),
  774.                   uG = (unsigned char) (Materials[Triangles[iTriangle].iMtrl].mtrl.diffuse.g * 255.f),
  775.                   uB = (unsigned char) (Materials[Triangles[iTriangle].iMtrl].mtrl.diffuse.b * 255.f);
  776.  
  777.     if (-1 == (iNewV[0] = iMakeVertex(
  778.                 (Vertices[Triangles[iTriangle].iSommets[0]].vPoint +
  779.                  Vertices[Triangles[iTriangle].iSommets[1]].vPoint
  780.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  781.  
  782.     if (-1 == (iNewV[1] = iMakeVertex(
  783.                 (Vertices[Triangles[iTriangle].iSommets[1]].vPoint +
  784.                  Vertices[Triangles[iTriangle].iSommets[2]].vPoint
  785.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  786.  
  787.     if (-1 == (iNewV[2] = iMakeVertex(
  788.                 (Vertices[Triangles[iTriangle].iSommets[2]].vPoint +
  789.                  Vertices[Triangles[iTriangle].iSommets[0]].vPoint
  790.                 ) / 2.f, XDC_ALLOWSAME))) return FALSE;
  791.  
  792.     if (-1 == (iNewT[0] = iMakeTriangle(iNewV[0], iNewV[1], iNewV[2], uR, uG, uB))) return FALSE;
  793.     if (-1 == (iNewT[1] = iMakeTriangle(iNewV[0], iNewV[1], Triangles[iTriangle].iSommets[1], uR, uG, uB))) return FALSE;
  794.     if (-1 == (iNewT[2] = iMakeTriangle(iNewV[1], iNewV[2], Triangles[iTriangle].iSommets[2], uR, uG, uB))) return FALSE;
  795.     if (-1 == (iNewT[3] = iMakeTriangle(iNewV[0], iNewV[2], Triangles[iTriangle].iSommets[0], uR, uG, uB))) return FALSE;
  796.  
  797.     Vertices[iNewV[0]].bSelected =
  798.     Vertices[iNewV[1]].bSelected =
  799.     Vertices[iNewV[2]].bSelected = Vertices[Triangles[iTriangle].iSommets[0]].bSelected;
  800.  
  801.     return bDeleteTriangle(iTriangle);
  802. }
  803.  
  804. BOOL    bIsTriangleSelected(int iTriangle)
  805. {
  806.     return
  807.         Triangles[iTriangle].bEnabled &&
  808.         bIsVertexSelected(Triangles[iTriangle].iSommets[0]) &&
  809.         bIsVertexSelected(Triangles[iTriangle].iSommets[1]) &&
  810.         bIsVertexSelected(Triangles[iTriangle].iSommets[2]);
  811. }
  812.  
  813. BOOL    bIsTrianglePartiallySelected(int iTriangle)
  814. {
  815.     return 
  816.         Triangles[iTriangle].bEnabled &&
  817.         (bIsVertexSelected(Triangles[iTriangle].iSommets[0]) ||
  818.          bIsVertexSelected(Triangles[iTriangle].iSommets[1]) ||
  819.          bIsVertexSelected(Triangles[iTriangle].iSommets[2]));
  820. }
  821.  
  822. //********************************************** O U T I L S *************************
  823. // Propager de façon **non** récursive la dé/sélection d'un vertex aux vertices connexes (à travers edges ou triangles)
  824. void vPropagateSelection(void)
  825. {
  826.     register BOOL bReste;
  827.  
  828.     bReste = TRUE;
  829.     while (bReste)
  830.     {
  831.         bReste = FALSE;
  832.  
  833.         for (register int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  834.             if (bIsEdgePartiallySelected(iEdge) && !bIsEdgeSelected(iEdge))
  835.                 bReste =
  836.                 Vertices[Edges[iEdge].iSommets[0]].bSelected = 
  837.                 Vertices[Edges[iEdge].iSommets[1]].bSelected = TRUE;
  838.     }
  839.  
  840.     bReste = TRUE;
  841.     while (bReste)
  842.     {
  843.         bReste = FALSE;
  844.  
  845.         for (register int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  846.             if (bIsTrianglePartiallySelected(iTria) && !bIsTriangleSelected(iTria))
  847.                 bReste =
  848.                 Vertices[Triangles[iTria].iSommets[0]].bSelected = 
  849.                 Vertices[Triangles[iTria].iSommets[1]].bSelected = 
  850.                 Vertices[Triangles[iTria].iSommets[2]].bSelected = TRUE;
  851.     }
  852. }
  853.  
  854. // Cloner la sélection
  855. BOOL bCloneSelection(D3DVECTOR vShift, BOOL bCloneMode)
  856. {
  857.     int iCnt, jCnt, iNumSelected, *iIndex;
  858.  
  859.     // Compter les points sélectionnés
  860.     iNumSelected = 0;
  861.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  862.         if (bIsVertexSelected(iCnt)) iNumSelected++;
  863.  
  864.     if (!iNumSelected) return FALSE;
  865.  
  866.     // Allouer la table de correspondance ancien / nouvel index
  867.     iIndex = (int *) malloc(iNumSelected * 2 * sizeof(int));
  868.  
  869.     // Cloner les points sélectionnés en conservant la table de correspondance ancien / nouveau
  870.     // et en décalant les nouveaux de vShift
  871.     jCnt = 0;
  872.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  873.     {
  874.         D3DVECTOR vVect = Vertices[iCnt].vPoint + vShift;
  875.  
  876.         if (!bIsVertexSelected(iCnt)) continue;
  877.  
  878.         // Remplir la table de correspondance ancien / nouveau
  879.         iIndex[jCnt] = iCnt;
  880.         iIndex[jCnt + 1] = iMakeVertex(vVect, XDC_FORCENEW);
  881.         jCnt += 2;
  882.     }
  883.  
  884.     // Cloner les arêtes éventuelles entre les anciens points
  885.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  886.     {
  887.         if (Edges[iCnt].bEnabled == FALSE) continue;
  888.  
  889.         int iOVert1 = Edges[iCnt].iSommets[0],
  890.             iOVert2 = Edges[iCnt].iSommets[1],
  891.             iCVert1 = -1,
  892.             iCVert2 = -1;
  893.  
  894.         // Vérifier que les deux sommets originaux de l'arête sont sélectionnés
  895.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2))
  896.         {
  897.             // Alors il faut créer une nouvelle arête avec les sommets clonés
  898.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  899.             {
  900.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  901.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  902.             }
  903.             if ((iCVert1 != -1) && (iCVert2 != -1))
  904.             {
  905.                 iMakeEdge(iCVert1, iCVert2);
  906.  
  907.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  908.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  909.                 {
  910.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, 0xFF, 0xFF, 0xFF);
  911.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, 0xFF, 0xFF, 0xFF);
  912.                 }
  913.             }
  914.         }
  915.     }
  916.  
  917.     // Cloner les triangles éventuels entre les différents points
  918.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  919.     {
  920.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  921.  
  922.         int iOVert1 = Triangles[iCnt].iSommets[0],
  923.             iOVert2 = Triangles[iCnt].iSommets[1],
  924.             iOVert3 = Triangles[iCnt].iSommets[2],
  925.             iCVert1 = -1,
  926.             iCVert2 = -1,
  927.             iCVert3 = -1;
  928.  
  929.         // Vérifier que les trois sommets originaux du triangle sont sélectionnés
  930.         if (bIsVertexSelected(iOVert1) && bIsVertexSelected(iOVert2) && bIsVertexSelected(iOVert3))
  931.         {
  932.             // Alors il faut créer un nouveau triangle avec les sommets clonés
  933.             for (jCnt = 0 ; jCnt < iNumSelected ; jCnt++)
  934.             {
  935.                 if (iIndex[jCnt * 2] == iOVert1) iCVert1 = iIndex[jCnt * 2 + 1];
  936.                 if (iIndex[jCnt * 2] == iOVert2) iCVert2 = iIndex[jCnt * 2 + 1];
  937.                 if (iIndex[jCnt * 2] == iOVert3) iCVert3 = iIndex[jCnt * 2 + 1];
  938.             }
  939.             if ((iCVert1 != -1) && (iCVert2 != -1) && (iCVert3 != -1))
  940.             {
  941.                 unsigned char uR = (unsigned char) (Materials[Triangles[iCnt].iMtrl].mtrl.diffuse.r * 255.f),
  942.                               uG = (unsigned char) (Materials[Triangles[iCnt].iMtrl].mtrl.diffuse.g * 255.f),
  943.                               uB = (unsigned char) (Materials[Triangles[iCnt].iMtrl].mtrl.diffuse.b * 255.f);
  944.  
  945.                 iMakeTriangle(iCVert1, iCVert2, iCVert3, uR, uG, uB);
  946.  
  947.                 // Si le mode de clonage est avec extrusion, créer les triangles de l'élévation
  948.                 if (bCloneMode == XDC_MODE_EXTRUDE)
  949.                 {
  950.                     iMakeTriangle(iOVert1, iCVert1, iCVert2, uR, uG, uB);
  951.                     iMakeTriangle(iOVert1, iOVert2, iCVert2, uR, uG, uB);
  952.                     iMakeTriangle(iOVert2, iCVert2, iCVert3, uR, uG, uB);
  953.                     iMakeTriangle(iOVert2, iOVert3, iCVert3, uR, uG, uB);
  954.                     iMakeTriangle(iOVert1, iCVert1, iCVert3, uR, uG, uB);
  955.                     iMakeTriangle(iOVert1, iOVert3, iCVert3, uR, uG, uB);
  956.                 }
  957.             }
  958.         }
  959.     }
  960.  
  961.     // Inverser la sélection (sélectionner les nouveaux points)
  962.     for (iCnt = 0 ; iCnt < iNumSelected ; iCnt++)
  963.     {
  964.         Vertices[iIndex[iCnt * 2    ]].bSelected = FALSE;
  965.         Vertices[iIndex[iCnt * 2 + 1]].bSelected = TRUE;
  966.     }
  967.  
  968.     // Libérer la table de correspondance
  969.     free(iIndex);
  970.  
  971.     return TRUE;
  972. }
  973.  
  974. // Cacher les éléments de la sélection
  975. void vHideSelection(void)
  976. {
  977.     int iVert, iCnt;
  978.  
  979.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  980.     {
  981.         if (bIsVertexSelected(iVert))
  982.         {
  983.             Vertices[iVert].bHidden = TRUE;
  984.             Vertices[iVert].bSelected = FALSE;
  985.  
  986.             for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  987.             {
  988.                 if (Edges[iCnt].bEnabled == FALSE) continue;
  989.  
  990.                 if (bVertInEdge(iVert, iCnt))
  991.                     Edges[iCnt].bHidden = TRUE;
  992.             }
  993.             for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  994.             {
  995.                 if (Triangles[iCnt].bEnabled == FALSE) continue;
  996.  
  997.                 if (bVertInTriangle(iVert, iCnt))
  998.                     Triangles[iCnt].bHidden = TRUE;
  999.             }
  1000.         }
  1001.     }
  1002. }
  1003.  
  1004. // Rendre visibles les éléments cachés
  1005. void vRevealHidden(void)
  1006. {
  1007.     int iCnt;
  1008.  
  1009.     for (iCnt = 0 ; iCnt <= iVertLastUsed ; iCnt++)
  1010.     {
  1011.         if (Vertices[iCnt].bEnabled == FALSE) continue;
  1012.  
  1013.         Vertices[iCnt].bHidden = FALSE;
  1014.     }
  1015.  
  1016.     for (iCnt = 0 ; iCnt <= iEdgeLastUsed ; iCnt++)
  1017.     {
  1018.         if (Edges[iCnt].bEnabled == FALSE) continue;
  1019.  
  1020.         Edges[iCnt].bHidden = FALSE;
  1021.     }
  1022.  
  1023.     for (iCnt = 0 ; iCnt <= iTriaLastUsed ; iCnt++)
  1024.     {
  1025.         if (Triangles[iCnt].bEnabled == FALSE) continue;
  1026.  
  1027.         Triangles[iCnt].bHidden = FALSE;
  1028.     }
  1029. }
  1030.  
  1031. // Déterminer le barycentre de la sélection
  1032. D3DVECTOR vCenter(void)
  1033. {
  1034.     D3DVECTOR dVect = D3DVECTOR(0.f, 0.f, 0.f);
  1035.     int jCnt = 0;
  1036.  
  1037.     for (int iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1038.         if (bIsVertexSelected(iVert))
  1039.         {
  1040.             // Mémoriser les coordonnées avant modification
  1041.             Vertices[iVert].vPointBack = Vertices[iVert].vPoint;
  1042.             
  1043.             // Compter les points
  1044.             jCnt++;
  1045.  
  1046.             // Additionner les coordonnées du point à celles du barycentre
  1047.             dVect.x += Vertices[iVert].vPoint.x;
  1048.             dVect.y += Vertices[iVert].vPoint.y;
  1049.             dVect.z += Vertices[iVert].vPoint.z;
  1050.         }
  1051.  
  1052.     if (!jCnt) 
  1053.     {
  1054.         vTrace("*** E0022 : Pas de sélection");
  1055.         return dVect;
  1056.     }
  1057.  
  1058.     // Moyenner la somme des points
  1059.     dVect.x /= jCnt;
  1060.     dVect.y /= jCnt;
  1061.     dVect.z /= jCnt;
  1062.  
  1063.     return dVect;
  1064. }
  1065.  
  1066. // Garbage collektor !-)
  1067. void vCollect(void)
  1068. {
  1069.     int iShift, iVert, iMtrl, *iMapTo;
  1070.  
  1071.     // Réindexer les arêtes
  1072.     iShift = 0;
  1073.  
  1074.     for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  1075.     {
  1076.         if (Edges[iEdge].bEnabled == FALSE)
  1077.         {
  1078.             while (Edges[iEdge + iShift].bEnabled == FALSE)
  1079.             {
  1080.                 iShift++;
  1081.                 iEdgeLastUsed--;
  1082.             }
  1083.         }
  1084.         if (iShift)
  1085.         {
  1086.             Edges[iEdge] = Edges[iEdge + iShift];
  1087.             Edges[iEdge + iShift].bEnabled = FALSE;
  1088.         }
  1089.     }
  1090.  
  1091.     iEdgeFirstAvailable = iEdgeLastUsed + 1;
  1092.  
  1093.     // Réindexer les triangles
  1094.     iShift = 0;
  1095.  
  1096.     for (int iTria = 0 ; iTria <= iTriaLastUsed ; iTria++)
  1097.     {
  1098.         if (Triangles[iTria].bEnabled == FALSE)
  1099.         {
  1100.             while (Triangles[iTria + iShift].bEnabled == FALSE)
  1101.             {
  1102.                 iShift++;
  1103.                 iTriaLastUsed--;
  1104.             }
  1105.         }
  1106.         if (iShift)
  1107.         {
  1108.             Triangles[iTria] = Triangles[iTria + iShift];
  1109.             Triangles[iTria + iShift].bEnabled = FALSE;
  1110.         }
  1111.     }
  1112.  
  1113.     iTriaFirstAvailable = iTriaLastUsed + 1;
  1114.  
  1115.     // Compter les sommets inutilisés pour ne faire la suite que s'il y en a
  1116.     iShift = 0;
  1117.  
  1118.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1119.         if (Vertices[iVert].bEnabled == FALSE)
  1120.             iShift++;
  1121.  
  1122.     if (!iShift)
  1123.         goto _DoneVert;
  1124.  
  1125.     // Allouer la table de mapping
  1126.     if (!(iMapTo = (int *) malloc((iVertLastUsed + 1) * sizeof(int))))
  1127.     {
  1128.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1129.         return;
  1130.     }
  1131.  
  1132.     // Préinitialiser la table de mapping
  1133.     for (iShift = 0 ; iShift <= iVertLastUsed ; iShift++)
  1134.         iMapTo[iShift] = iShift;
  1135.  
  1136.     // Réindexer les sommets
  1137.     iShift = 0;
  1138.  
  1139.     for (iVert = 0 ; iVert <= iVertLastUsed ; iVert++)
  1140.     {
  1141.         if (Vertices[iVert].bEnabled == FALSE)
  1142.         {
  1143.             while (Vertices[iVert + iShift].bEnabled == FALSE)
  1144.             {
  1145.                 iShift++;
  1146.                 iVertLastUsed--;
  1147.             }
  1148.         }
  1149.  
  1150.         if (iShift)
  1151.         {
  1152.             Vertices[iVert] = Vertices[iVert + iShift];
  1153.             Vertices[iVert + iShift].bEnabled = Vertices[iVert + iShift].bSelected = FALSE;
  1154.             iMapTo[iVert + iShift] = iVert;
  1155.         }
  1156.     }
  1157.  
  1158.     iVertFirstAvailable = iVertLastUsed + 1;
  1159.  
  1160.     // Réindexer les sommets dans les arêtes
  1161.     for(iShift = 0 ; iShift <= iEdgeLastUsed ; iShift++)
  1162.     {
  1163.         Edges[iShift].iSommets[0] = iMapTo[Edges[iShift].iSommets[0]];
  1164.         Edges[iShift].iSommets[1] = iMapTo[Edges[iShift].iSommets[1]];
  1165.     }
  1166.  
  1167.     // Réindexer les sommets dans les triangles
  1168.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1169.     {
  1170.         Triangles[iShift].iSommets[0] = iMapTo[Triangles[iShift].iSommets[0]];
  1171.         Triangles[iShift].iSommets[1] = iMapTo[Triangles[iShift].iSommets[1]];
  1172.         Triangles[iShift].iSommets[2] = iMapTo[Triangles[iShift].iSommets[2]];
  1173.     }
  1174.  
  1175.     // Libérer la table
  1176.     free(iMapTo);
  1177.  
  1178. _DoneVert:
  1179.  
  1180.     // Compter les matériaux inutilisés pour ne faire la suite que s'il y en a
  1181.     iShift = 0;
  1182.  
  1183.     for (iMtrl = 0 ; iMtrl <= iMtrlLastUsed ; iMtrl++)
  1184.         if (Materials[iMtrl].bEnabled == FALSE)
  1185.             iShift++;
  1186.  
  1187.     if (!iShift)
  1188.         return;
  1189.  
  1190.     // Allouer la table de mapping
  1191.     if (!(iMapTo = (int *) malloc((iMtrlLastUsed + 1) * sizeof(int))))
  1192.     {
  1193.         vTrace("*** E0032 : erreur malloc table mapping GC");
  1194.         return;
  1195.     }
  1196.  
  1197.     // Préinitialiser la table de mapping
  1198.     for (iShift = 0 ; iShift <= iMtrlLastUsed ; iShift++)
  1199.         iMapTo[iShift] = iShift;
  1200.  
  1201.     // Réindexer les matériaux
  1202.     iShift = 0;
  1203.  
  1204.     for (iMtrl = 0 ; iMtrl <= iMtrlLastUsed ; iMtrl++)
  1205.     {
  1206.         if (Materials[iMtrl].bEnabled == FALSE)
  1207.         {
  1208.             while (Materials[iMtrl + iShift].bEnabled == FALSE)
  1209.             {
  1210.                 iShift++;
  1211.                 iMtrlLastUsed--;
  1212.             }
  1213.         }
  1214.  
  1215.         if (iShift)
  1216.         {
  1217.             Materials[iMtrl] = Materials[iMtrl + iShift];
  1218.             Materials[iMtrl + iShift].bEnabled = FALSE;
  1219.             iMapTo[iMtrl + iShift] = iMtrl;
  1220.         }
  1221.     }
  1222.  
  1223.     iMtrlFirstAvailable = iMtrlLastUsed + 1;
  1224.  
  1225.     // Réindexer les matériaux dans les triangles
  1226.     for(iShift = 0 ; iShift <= iTriaLastUsed ; iShift++)
  1227.         Triangles[iShift].iMtrl = iMapTo[Triangles[iShift].iMtrl];
  1228.  
  1229.     // Libérer la table
  1230.     free(iMapTo);
  1231. }
  1232.